﻿using System;
using System.Threading;

namespace BlueMarble.Genesis.Infrastructure.Security
{
    public class Authentication
    {
        protected AuthenticationServiceReference.AuthenticationService authenticationService;

        protected Membership membership;

        public Authentication()
        {
            this.connectService();

            membership = new Membership();
        }

        public void ValidateUser(string Username, string Password)
        {
            ManualResetEvent resetEvent = new ManualResetEvent(false);

            bool validUser = false;

            IAsyncResult asyncResult = this.authenticationService.BeginValidateUser(Username, Password, null, v =>
                {
                    try { validUser = this.authenticationService.EndValidateUser(v); }
                    finally { resetEvent.Set(); }
                }, null);

            ThreadPool.QueueUserWorkItem((o) =>
                {
                    WaitHandle.WaitAll(new WaitHandle[] { resetEvent });

                    if (this.ValidUserCompleted != null)
                    {
                        this.ValidUserCompleted(validUser);
                    }
                });
        }

        public void Login(string Username, string Password)
        {
            ManualResetEvent resetEvent = new ManualResetEvent(false);

            bool login = false;

            IAsyncResult asyncResult = this.authenticationService.BeginLogin(Username, Password, "", true, v =>
                {
                    try { login = this.authenticationService.EndLogin(v); }
                    finally { resetEvent.Set(); }
                }, null);

            ThreadPool.QueueUserWorkItem((o) =>
                {
                    WaitHandle.WaitAll(new WaitHandle[] { resetEvent });

                    if (this.LoginCompleted != null)
                    {
                        this.LoginCompleted(login);
                    }
                });
        }

        public void Logout()
        {
            ManualResetEvent resetEvent = new ManualResetEvent(false);
            
            IAsyncResult asyncResult = this.authenticationService.BeginLogout(v =>
            {
                try { this.authenticationService.EndLogout(v); }
                finally { resetEvent.Set(); }
            }, null);

            ThreadPool.QueueUserWorkItem((o) =>
            {
                WaitHandle.WaitAll(new WaitHandle[] { resetEvent });

                if (this.LogoutCompleted != null)
                {
                    this.LogoutCompleted();
                }
            });
        }

        public void IsLoggedIn()
        {
            ManualResetEvent resetEvent = new ManualResetEvent(false);

            bool isLoggedIn = false;

            this.authenticationService.BeginIsLoggedIn(v =>
            {
                try { isLoggedIn = this.authenticationService.EndIsLoggedIn(v); }
                finally { resetEvent.Set(); }
            }, null);

            ThreadPool.QueueUserWorkItem((o) =>
            {
                WaitHandle.WaitAll(new WaitHandle[] { resetEvent });

                if (this.IsLoggedInCompleted != null)
                {
                    this.IsLoggedInCompleted(isLoggedIn);
                }
            });
        }

        protected void connectService()
        {
            if (this.authenticationService == null)
            {
                this.authenticationService = new AuthenticationServiceReference.AuthenticationServiceClient();
            }
        }

        public event IsLoggedInEventHandler IsLoggedInCompleted;
        public event LoginEventHandler LoginCompleted;
        public event LogoutEventHandler LogoutCompleted;
        public event ValidUserEventHandler ValidUserCompleted;
    }

    public delegate void IsLoggedInEventHandler(bool IsLoggedIn);
    public delegate void LoginEventHandler(bool Login);
    public delegate void LogoutEventHandler();
    public delegate void ValidUserEventHandler(bool ValidUser);
}
